va_arg関数、va_start関数、va_end関数を使って、可変引数リストから引数の値を取得することができます。va_start関数は引数リストの初期化を、va_end関数は引数リストのリセットを行います。そして、va_arg関数で引数の値を取得します。これらの関数は、マクロとして実装されているかもしれません。

#include <stdarg.h>
void va_start(va_list ap, last);
type va_arg(va_list ap, type);
void va_end(va_list ap);

apは引数リストを格納する領域を指定します。
lastは固定引数の最後の引数を指定します。
typeは取得する引数の型名を指定します。

これらの関数は同じ関数内で、va_start関数、va_arg関数、va_end関数の順に呼び出さなければなりません。そして、va_arg関数を呼び出す毎に引数リストから引数の値が取り出されます。

次の例題プログラムのVarPrint関数は第1引数は固定ですが、第2引数以降が可変になります。第1引数の文字列で、第2引数以降の引数の数と型名を指定しています。ちなみに、’c’は文字、’d’はdouble型浮動小数点数、’i’はint型整数、’s’は文字列を表します。

プログラム 例

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>

int main()
{
  /* ユーザ定義関数の宣言 */
  void VarPrint(char *Format, ...);

  printf('1回目\n');
  VarPrint('cdis', 'A', 3.14, 3, 'Hello.');

  printf('\n2回目\n');
  VarPrint('siiddccc', 'World.', 1, 2, 1.234, 56.789, 'a', 'b', 'c');

  return 0;
}

/* 可変引数リストの値の表示 */
void VarPrint(char *p_format, ...)
{
  va_list    ap;

  /* 可変引数リストの初期化 */
  va_start(ap, p_format);

  while (*p_format) {
    switch (*p_format) {
      case 'c':
        printf('%c\n', (char)va_arg(ap, int));
        break;
      case 'd':
        printf('%f\n', va_arg(ap, double));
        break;
      case 'i':
        printf('%d\n', va_arg(ap, int));
        break;
      case 's':
        printf('%s\n', va_arg(ap, char *));
        break;
      default:
        printf('引数の型名が不当です\n');
    }

    ++p_format;
  }
  /* 可変引数リストのリセット */
  va_end(ap);

  return;
}

例の実行結果

$ ./va_arg.exe
1回目
A
3.140000
3
Hello.

2回目
World.
1
2
1.234000
56.789000
a
b
c
$